/**
 * Copyright(c) Hainan eKing Technology co., LTD
 *
 * @date 2013年8月13日
 * 	
 * Original Author: 郑兴(zhengxing)
 *
 * ChangeLog
 *
 */
package com.hnas.sys.service.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hnas.core.dao.PageBean;
import com.hnas.core.dto.DTOPagedList;
import com.hnas.core.util.StringUtil;
import com.hnas.sys.dao.AuthorityDAO;
import com.hnas.sys.dao.AuthorityResourceDAO;
import com.hnas.sys.dao.MenuPackageDAO;
import com.hnas.sys.dao.ResourceDAO;
import com.hnas.sys.domain.ResourceStatus;
import com.hnas.sys.orm.Authority;
import com.hnas.sys.orm.AuthorityResource;
import com.hnas.sys.orm.MenuPackage;
import com.hnas.sys.orm.Resource;
import com.hnas.sys.service.system.criteria.DTOSearchAuthority;
import com.hnas.sys.service.system.data.DTOMenu;
import com.hnas.sys.service.system.data.DTOOperate;
import com.hnas.sys.service.system.data.DTOPackage;
import com.hnas.sys.service.system.domain.OperateType;
import com.hnas.sys.service.system.dto.DTOAuthority;
import com.hnas.sys.service.system.mapper.AuthorityMapper;
import com.hnas.sys.service.system.mapper.MenuPackageMapper;
//import com.sun.org.apache.commons.beanutils.BeanUtils;

/**
 * <pre>权限服务接口实现类</pre>
 * @author 郑兴(zhengxing)
 *
 */
@Component("authorityService")
@Transactional
public class AuthorityServiceImpl implements AuthorityService {
	private Logger log = LoggerFactory.getLogger(AuthorityServiceImpl.class);
	
	@Autowired
	private AuthorityDAO authorityDAO;
	@Autowired
	private ResourceDAO resourceDAO;
	@Autowired
	private AuthorityResourceDAO authorityResourceDAO;
	
	/* (non-Javadoc)
	 * @see com.hna.dt.service.system.AuthorityService#loadAll()
	 */

	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<DTOAuthority> loadAll() {
//		return AuthorityMapper.getInstance().mapToValues(authorityDAO.loadAll());
		return this.getAllAuthorities();
	}
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public List<DTOAuthority> getAllAuthorities() {
		List<DTOAuthority> aus = new ArrayList<DTOAuthority>();
		for (Authority au:this.authorityDAO.getAllAuthorities()){
			aus.add(AuthorityMapper.getInstance().mapToValue2(au));
		}
		return aus;
//		return AuthorityMapper.getInstance().mapToValues(
//				authorityDAO.getAllAuthorities());
	}

	/* (non-Javadoc)
	 * @see com.hna.dt.service.system.AuthorityService#load(java.lang.Long)
	 */
	@Transactional(readOnly=true, propagation=Propagation.REQUIRED)
	public DTOAuthority load(Long id) {
		Authority authority = authorityDAO.find(id);
		DTOAuthority dto = AuthorityMapper.getInstance().mapToValue(authority);
		return dto;
	}
	@Value(value = "#{component['resource.defaultResouce']}")
private String backendResourceUrl = "/backend/";
	/* (non-Javadoc)
	 * @see com.hna.dt.service.system.AuthorityService#saveOrUpdate(com.hna.dt.service.system.dto.DTOAuthority)
	 */
	public void saveOrUpdate(DTOAuthority dto, boolean operateTypeOnly) {
		Authority vo = null;//AuthorityMapper.getInstance().mapToEntity(dto);
//		updateAuthorityResource(authority, dto.getResourceIDs());
		if(null == dto || null == dto.getId() || dto.getId() == 0) {
			vo = new Authority();			
		} else {
			vo = this.authorityDAO.find(dto.getId());			
		}
		BeanUtils.copyProperties(dto, vo, new String[]{"id"});
		vo.setStatus(ResourceStatus.VALID);
		Map<Long,AuthorityResource> as = new HashMap<Long,AuthorityResource>();
		for (AuthorityResource au:vo.getAuthorityResources()){
			as.put(au.getResource().getId(), au);
			au.setAuthority(null);
		}
		vo.getAuthorityResources().clear();
		//加载当前资源
		List<Resource> rs = this.resourceDAO.getResourceByIds(dto.getResourceIds());
		if (operateTypeOnly)//仅操作类型
			rs.addAll(this.resourceDAO.getResourceRefs(dto.getResourceIds()));
		for (Resource rc:rs){
			AuthorityResource au = as.get(rc.getId());
			if (null!=au){
//				as.remove(rc.getId());
				if (null==au.getAuthority()){
					au.setAuthority(vo);
					vo.getAuthorityResources().add(au);
				}				
			}else{
				au = new AuthorityResource();
				au.setAuthority(vo);
				au.setResource(rc);
				as.put(rc.getId(), au);
//				this.authorityResourceDAO.persist(au);
				vo.getAuthorityResources().add(au);
			}
		
		}
		for (AuthorityResource au:as.values()){
			if(null==au.getAuthority()){
				if (!operateTypeOnly){//全部类型
					this.authorityResourceDAO.remove(au);
				}
				else if (au.getResource().getOperateType()>0)
					this.authorityResourceDAO.remove(au);//仅操作类型
				else{
					au.setAuthority(vo);
					vo.getAuthorityResources().add(au);
				}
			}
		}
		//添加后台默认权限
		Resource defaultResouce = this.resourceDAO.loadResource(backendResourceUrl);
		if (null!=defaultResouce){
			boolean hasDefault = false;
			for (AuthorityResource au:vo.getAuthorityResources()){
				if (au.getResource().getId()==defaultResouce.getId()){
					hasDefault = true;
					break;
				}
			}
			if (!hasDefault){
				AuthorityResource	au = new AuthorityResource();
				au.setAuthority(vo);
				au.setResource(defaultResouce);
				vo.getAuthorityResources().add(au);
			}			
		}
		if (vo.getId()==0){
			authorityDAO.persist(vo);
		}else
			authorityDAO.merge(vo);
	} 
	
	/**
	 * <pre>更新权限对应资源，</pre>
	 * @Auther 郑兴(zhengxing)
	 * @date 2013年8月28日 下午11:16:25
	 * @param authority
	 * @param resourceIDs
	 */
//	private void updateAuthorityResource(Authority authority, String resourceIDs) {
//		if(StringUtil.isNotEmpty(resourceIDs)) {
//			Set<AuthorityResource> ases = new HashSet<AuthorityResource>();
//			Authority old = authority.getId() > 0 ? authorityDAO.find(authority.getId()) : authority;
//			StringBuffer oldResourceIDs = new StringBuffer();
//			Set<AuthorityResource> oldases = old.getAuthorityResources();
//			for(AuthorityResource as : oldases) {
//				oldResourceIDs.append(as.getResource().getId()).append(",");
//			}
//			String[] ids = resourceIDs.split(",");
//			for(String id : ids) {
//				/*旧资源中没有，就是需要添加的*/
//				if(oldResourceIDs.indexOf(id + ",") == -1) {
//					Resource resource = resourceDAO.find(Long.parseLong(id));
//					AuthorityResource as = new AuthorityResource();
//					as.setAuthority(authority);
//					as.setResource(resource);
//					ases.add(as);
//				}
//			}
//			authority.setAuthorityResources(ases);
//			for(AuthorityResource as : oldases) {
//				/*新资源中没有的需要删除*/
//				if(resourceIDs.indexOf(as.getResource().getId() + "") == -1) {
//					authorityResourceDAO.remove(as);
//				}
//			}
//		}
//	}

	
	public DTOAuthority loadAuthorityByName(String AuthorityName) {
		DTOAuthority dto = null;
		Authority authority = authorityDAO.loadAuthorityByName(AuthorityName);
		if(null != authority){
			dto = AuthorityMapper.getInstance().mapToValue(authority);
		}
		return dto;
	}
	public DTOPagedList<DTOAuthority> search(DTOSearchAuthority con) {
		// TODO Auto-generated method stub
//		return null;
		PageBean<Authority> page = new PageBean<Authority>();
		page.setPageNo(con.getPageNo());
		page.setPageSize(con.getPageSize());
		page.setTotalCount(con.getTotalCount());
		StringBuffer sb = new StringBuffer();
		List<String> paras = new ArrayList<String>();
		int j=1;
		sb.append(" and t.statusStr='VALID'");
//		if (null!=con.getDto()){
		if (StringUtil.isNotEmpty(con.getName())) {
			sb.append(" and t.name like ?" + j++);
			paras.add("%"+con.getName().trim()+"%");
		}
//		}
		if (sb.length() > 0) {
			sb.delete(0, 5);
			sb.insert(0, " from Authority t where ");
		} else {
			sb.append(" from Authority t");
		}
		page.setQuery(sb.toString());
		page.setQueryCount("select count(t.id) " + sb);
//		page.setQuery(sb.insert(" from Authority t".length(), " join fetch t.product ").toString());
		this.authorityDAO.queryByPage(page, paras.toArray());
		DTOPagedList<DTOAuthority> pageList = new DTOPagedList<DTOAuthority>();
		pageList.setPageNo(page.getPageNo());
		pageList.setPageSize(page.getPageSize());
		pageList.setTotalCount(page.getTotalCount());
		List<DTOAuthority> ls = new ArrayList<DTOAuthority>();
		for (Authority or : page.getList()) {
			DTOAuthority dto = new DTOAuthority();
			dto = AuthorityMapper.getInstance().mapToValue2(or);
			
			ls.add(dto);
		}
		pageList.setList(ls);
		return pageList;
	}
	public void disable(long id) {
		// TODO Auto-generated method stub
		Authority vo = this.authorityDAO.find(id);
		vo.setStatus(ResourceStatus.INVALID);
		this.authorityDAO.merge(vo);
	}
	@Autowired
	private MenuPackageDAO menuPackageDAO;
	public List<DTOPackage> getAuthorityForDisplay(long id) {
		// TODO Auto-generated method stub		
		 Set<Long> rcs = null;
		 if (id==0){
			 rcs = new HashSet<Long>(0);
		 }else{
			 Authority vo = this.authorityDAO.find(id);
			 rcs = new HashSet<Long>(vo.getAuthorityResources().size());
			 for(AuthorityResource au:vo.getAuthorityResources()){
				 rcs.add(au.getResource().getId());
			 }
		 }
//		vo.getAuthorityResources();
		String hql = "from Resource r where r.operateType>0 and r.statusStr=?1 order by menuPackageID,priority,operateType";
		List<Resource> rs = this.resourceDAO.findByQuery(hql, ResourceStatus.VALID.getAlias());
		Map<Long,DTOPackage> packs = new HashMap<Long,DTOPackage>();
		 List<DTOPackage> ls = new ArrayList<DTOPackage>();
		 long lastPack = -1;
		 Map<String,DTOMenu> menus = null;
		 for (Resource rc:rs){
			 DTOPackage pck = packs.get(rc.getMenuPackageID());
			 if (null==pck){
				 //添加主菜单
				 pck = new DTOPackage();
				 MenuPackage pc = this.menuPackageDAO.find(rc.getMenuPackageID());
				 pck.setPack(MenuPackageMapper.getInstance().mapToValue(pc));
				 packs.put(pc.getId(), pck);
				 if (ls.size()%2==0){
					 pck.setOdd(true);//奇数
				 }
				 ls.add(pck);
			 }
			 //添加菜单项
			 if (lastPack==-1 || lastPack!=rc.getMenuPackageID())
				 menus = new HashMap<String, DTOMenu>();//菜单项
			 lastPack = rc.getMenuPackageID();
			 DTOMenu menu = menus.get(rc.getName());
			 if (null==menu){
				 menu = new DTOMenu();
				 menu.setId(rc.getId());
				 menu.setIndex(pck.getMenus().size()+1);
				 pck.getMenus().add(menu);
				 menu.setMenuName(rc.getName());
				 menus.put(menu.getMenuName(), menu);
			 }else{
				 
			 }
			 if (menu.getOpts().contains(rc.getOperateType())){
				 
			 }else{
				 DTOOperate op = new DTOOperate();
				 op.setResourceId(rc.getId());
				 menu.getOpts().add(rc.getOperateType());
				 op.setOperateName(OperateType.getOperateType(rc.getOperateType()));
				 menu.getOperates().add(op);
				 if (rcs.contains(rc.getId())){
					 op.setChecked(true);
				 }
			 }
			
		 }
		 for (DTOPackage pck:ls){
			 pck.setMenuSize(pck.getMenus().size());
			 for (DTOMenu menu:pck.getMenus()){
				 if (menu.getOpts().size()<4){
					 for (int i=menu.getOpts().size();i<4;i++){
						 menu.getOperates().add(new DTOOperate());
					 }
				 }
			 }
		 }
		 if (ls.size()>0)
			 ls.get(ls.size()-1).setLast(true);
		return ls;
	}
}
